#include "gd32f30x.h"
#include "veml7700.h"
#include "i2c.h"
#include <stdio.h>

void veml7700_write(uint8_t reg_addr,uint8_t *p_buf)
{
#if I2C1_MODE == I2C1_MODE_SW
    swi2c_device_write_data(VEML_SLAVE_ADDR,&reg_addr,1,p_buf,2);
#endif
}

void veml7700_read(uint8_t reg_addr,uint8_t *p_buf)
{
#if I2C1_MODE == I2C1_MODE_SW
    swi2c_device_read_data(VEML_SLAVE_ADDR,&reg_addr,1,p_buf,2);
#endif
}

static int get_veml7700_default_value(uint16_t *default_value)
{
    uint8_t rx_data[2] = {0};
    veml7700_read(0x00,rx_data);
    *default_value = ((rx_data[1] << 8) | rx_data[0]);
    return 0;
}

static uint16_t veml7700_get_light_sensor_value(uint8_t command,uint16_t mask,uint8_t shift)
{
    uint8_t rx_data[2] = {0};
    uint16_t r_value = 0;

    veml7700_read(command,rx_data);
    r_value = ((rx_data[1] << 8) | rx_data[0]);
    return (r_value & mask) >> shift;
}

static void veml7700_set_light_sensor_value(uint8_t value,uint8_t command,uint16_t mask,uint8_t shift)
{
    uint8_t rx_data[2] = {0};
    uint8_t tx_data[2] = {0};
    uint16_t r_value = 0;
    uint16_t tmp_value = 0;
    veml7700_read(command,rx_data);
    r_value = ((rx_data[1] << 8) | rx_data[0]);
    tmp_value = r_value & ~(mask);
    tmp_value |= ((value << shift) & mask);

    tx_data[0] = tmp_value & 0xff;
    tx_data[1] = ((tmp_value >> 8) & 0xff); 
    veml7700_write(command,tx_data);
} 

static uint16_t get_power_enable()
{
    return veml7700_get_light_sensor_value(COMMAND_ALS_SD,ALS_SD_MASK,ALS_SD_SHIFT);
}

static void set_power_enable(int enable)
{
    return veml7700_set_light_sensor_value(enable,COMMAND_ALS_SD,ALS_SD_MASK,ALS_SD_SHIFT);
}

static uint16_t get_gain_value()
{
    return veml7700_get_light_sensor_value(COMMAND_ALS_GAIN,ALS_GAIN_MASK,ALS_GAIN_SHIFT);
}

static void set_gain_value(uint16_t gain)
{
    veml7700_set_light_sensor_value(gain,COMMAND_ALS_GAIN,ALS_GAIN_MASK,ALS_GAIN_SHIFT);
}

static uint16_t get_interrupt_enable()
{
    return veml7700_get_light_sensor_value(COMMAND_ALS_INT_EN,ALS_INT_EN_MASK,ALS_INT_EN_SHIFT);
}

static void set_interrupt_enable(uint16_t enable)
{
    veml7700_set_light_sensor_value(enable,COMMAND_ALS_INT_EN,ALS_INT_EN_MASK,ALS_INT_EN_SHIFT);
}

static int get_integration_time() 
{
    return veml7700_get_light_sensor_value(COMMAND_ALS_IT,ALS_IT_MASK,ALS_IT_SHIFT);
   
}

static void set_integration_time(int time)
{
    veml7700_set_light_sensor_value(time,COMMAND_ALS_IT,ALS_IT_MASK,ALS_IT_SHIFT);
}

static int get_power_saving_mode() 
{
    return veml7700_get_light_sensor_value(COMMAND_PSM_EN,PSM_EN_MASK,PSM_EN_SHIFT);
}


static void set_power_saving_mode(int mode)
{
    veml7700_set_light_sensor_value(mode,COMMAND_PSM_EN,PSM_EN_MASK,PSM_EN_SHIFT);
}

static uint16_t get_als_reg_data()
{
    uint8_t rx_data[2] = {0};
    uint16_t r_value = 0;
 
    veml7700_read(COMMAND_ALS_DATA,rx_data);
    r_value = ((rx_data[1] << 8) | rx_data[0]);
    return r_value;
}

static int normalize_resolution(int value)
{
    switch (get_gain_value())
    {

        case ALS_GAIN_X2:
        value /= 2.0;
        break;
        case ALS_GAIN_d4:
            value *= 4;
            break;
        case ALS_GAIN_d8:
            value *= 8;
            break;
        case ALS_GAIN_X1:
        default:break;
        
    }
    switch (get_integration_time()){

        case ALS_INTEGRATION_25ms:
            value *= 4;
            break;
        case ALS_INTEGRATION_50ms:
            value *= 2;
            break;
        case ALS_INTEGRATION_200ms:
            value /= 2.0;
            break;
        case ALS_INTEGRATION_400ms:
            value /= 4.0;
            break;
        case ALS_INTEGRATION_800ms:
            value /= 8.0;
            break;
        case ALS_INTEGRATION_100ms:
        default:break;
    }
    return value;    

} 

int get_lux_data(void)
{
    return normalize_resolution(get_als_reg_data() * 0.0576);
}

void veml7700_init(void)
{
    uint16_t default_value;
    get_veml7700_default_value(&default_value);
 
    if (default_value == 0x0001)
    {
        printf("Have Fined Veml7700!\r\n");
    }
    else
    {
        printf("Veml7700 not exsit %x\r\n",default_value);
        //return ;
    }

    set_power_enable(ALS_POWER_SHUTDOWN);
    printf("get_power_enable %d\r\n",get_power_enable());

    set_interrupt_enable(ALS_INTERRUPT_DISABLE);

    set_gain_value(ALS_GAIN_d8);
    printf("get_gain_value == %d\r\n",get_gain_value());

    set_integration_time(ALS_INTEGRATION_100ms);

    set_power_saving_mode(ALS_POWER_MODE_DISABLE);

    set_power_enable(ALS_POWER_ON);
}